package com.jingdianjichi.subject.domain.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.jingdianjichi.subject.common.enums.IsDeletdFlageEnum;
import com.jingdianjichi.subject.domain.config.ThreadPoolConfig;
import com.jingdianjichi.subject.domain.convert.SubjectCategoryConverter;
import com.jingdianjichi.subject.domain.entity.SubjectCategoryBO;
import com.jingdianjichi.subject.domain.entity.SubjectLabelBO;
import com.jingdianjichi.subject.domain.service.SubjectCategoryDomainService;
import com.jingdianjichi.subject.domain.utils.CacheUtils;
import com.jingdianjichi.subject.infra.basic.entity.SubjectCategory;
import com.jingdianjichi.subject.infra.basic.entity.SubjectLabel;
import com.jingdianjichi.subject.infra.basic.entity.SubjectMapping;
import com.jingdianjichi.subject.infra.basic.service.SubjectCategoryService;
import com.jingdianjichi.subject.infra.basic.service.SubjectLabelService;
import com.jingdianjichi.subject.infra.basic.service.SubjectMappingService;
import com.sun.javaws.CacheUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * SubjectCategoryDomainServiceImpl 类
 *
 * @author 熊苏鹏1
 * @date 2025/1/30 17:12
 * @description 无
 */
@Service
@Slf4j
public class SubjectCategoryDomainServiceImpl implements SubjectCategoryDomainService {
    @Resource
    private SubjectCategoryService subjectCategoryService;
    @Resource
    private SubjectMappingService subjectMappingService;
    @Resource
    SubjectLabelService subjectLabelService;
    @Resource
    ThreadPoolExecutor labelThreadPool;
    //本地缓存，用来存储不同大类下的小分类和标签
    @Resource
    CacheUtils cacheUtils;


    @Override
    public void add(SubjectCategoryBO subjectCategoryBO) {
        if(log.isInfoEnabled())
            log.info("SubjectCategoryDomainServiceImpl add bo:{}", JSON.toJSONString(subjectCategoryBO));
        SubjectCategory subjectCategory = SubjectCategoryConverter.INSTANCE.convertBoToCategory(subjectCategoryBO);
        subjectCategory.setIsDeleted(IsDeletdFlageEnum.NOT_DELETED.getCode());
        subjectCategoryService.insert(subjectCategory);
    }

    @Override
    public List<SubjectCategoryBO> queryPrimaryCategory(SubjectCategoryBO subjectCategoryBO) {
        subjectCategoryBO.setIsDeleted(IsDeletdFlageEnum.NOT_DELETED.getCode());
        SubjectCategory subjectCategory = SubjectCategoryConverter.INSTANCE.convertBoToCategory(subjectCategoryBO);
        List<SubjectCategory> subjectCategoryList = subjectCategoryService.queryCategoryList(subjectCategory);
        List<SubjectCategoryBO> subjectCategoryBOS = SubjectCategoryConverter.INSTANCE.convertCategoryListToBoList(subjectCategoryList);
        subjectCategoryBOS.forEach(item -> {
            Integer i = subjectCategoryService.queryCategoryCount(item.getId());
            item.setCategoryCount(i);
        });
        if(log.isInfoEnabled())
            log.info("SubjectCategoryDomainServiceImpl query entity:{}", JSON.toJSONString(subjectCategoryList));
        return subjectCategoryBOS;
    }

    @Override
    public Boolean update(SubjectCategoryBO subjectCategoryBO) {
        SubjectCategory subjectCategory = SubjectCategoryConverter.INSTANCE.convertBoToCategory(subjectCategoryBO);
        int update = subjectCategoryService.update(subjectCategory);
        return update > 0;
    }

    @Override
    public Boolean delete(SubjectCategoryBO subjectCategoryBO) {
        SubjectCategory subjectCategory = SubjectCategoryConverter.INSTANCE.convertBoToCategory(subjectCategoryBO);
        subjectCategory.setIsDeleted(IsDeletdFlageEnum.DELETED.getCode());
        if(log.isInfoEnabled())
            log.info("SubjectCategoryDomainServiceImpl delete entity:{}", JSON.toJSONString(subjectCategory));
        int delete = subjectCategoryService.update(subjectCategory);
        return delete > 0;

    }
    @SneakyThrows
    @Override
    public List<SubjectCategoryBO> queryCategoryAndLabel(SubjectCategoryBO subjectCategoryBO) {
        String key = "categoryAndLabel_" + subjectCategoryBO.getId();
        List<SubjectCategoryBO> result = cacheUtils.getResult(key, SubjectCategoryBO.class, (key_) -> {
            return getSubjectCategoryBOS(subjectCategoryBO);
        });

        return  result;
    }

    private List<SubjectCategoryBO> getSubjectCategoryBOS(SubjectCategoryBO subjectCategoryBO) {
        //查询当前大类下所有分类
        SubjectCategory subjectCategory = new SubjectCategory();
        subjectCategory.setParentId(Long.valueOf(subjectCategoryBO.getId()));
        subjectCategory.setIsDeleted(IsDeletdFlageEnum.NOT_DELETED.getCode());
        List<SubjectCategory> subjectCategoryList = subjectCategoryService.queryCategoryList(subjectCategory);
        if (log.isInfoEnabled()) {
            log.info("SubjectCategoryController.queryCategoryAndLabel.subjectCategoryList:{}",
                    JSON.toJSONString(subjectCategoryList));
        }
        List<SubjectCategoryBO> categoryBOList = SubjectCategoryConverter.INSTANCE.convertCategoryListToBoList(subjectCategoryList);
        //一次获取标签信息
        Map<Long, List<SubjectLabelBO>> labelMap = new HashMap<>();
        List<CompletableFuture<Map<Long, List<SubjectLabelBO>>>> collect = categoryBOList.stream().map(
                item -> CompletableFuture.supplyAsync(() -> getLabelBOList(item), labelThreadPool)
        ).collect(Collectors.toList());
        for (CompletableFuture<Map<Long, List<SubjectLabelBO>>> item : collect){

             try {
                 Map<Long, List<SubjectLabelBO>> longListMap = item.get();
                 if (CollectionUtils.isEmpty(longListMap)){
                     continue;
                 }
                 labelMap.putAll(longListMap);
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             } catch (ExecutionException e) {
                 throw new RuntimeException(e);
             }

         }
        ;
        categoryBOList.forEach(item -> item.setSubjectLabelBOS(labelMap.get(Long.valueOf(item.getId()))));
        return categoryBOList;
    }

    private Map<Long, List<SubjectLabelBO>> getLabelBOList(SubjectCategoryBO category) {
        Map<Long, List<SubjectLabelBO>> labelMap = new HashMap<>();
        SubjectMapping subjectMapping = new SubjectMapping();
        subjectMapping.setCategoryId(Long.valueOf(category.getId()));
        List<SubjectMapping> mappingList = subjectMappingService.queryLabelId(subjectMapping);
        if (CollectionUtils.isEmpty(mappingList)) {
            return null;
        }
        List<Long> labelIdList = mappingList.stream().map(SubjectMapping::getLabelId).collect(Collectors.toList());
        List<SubjectLabel> labelList = subjectLabelService.queryBatchById(labelIdList);
        List<SubjectLabelBO> labelBOList = new LinkedList<>();
        labelList.forEach(label -> {
            SubjectLabelBO subjectLabelBO = new SubjectLabelBO();
            subjectLabelBO.setId(label.getId());
            subjectLabelBO.setLabelName(label.getLabelName());
            subjectLabelBO.setCategoryId(label.getCategoryId());
            subjectLabelBO.setSortNum(label.getSortNum());
            labelBOList.add(subjectLabelBO);
        });
        labelMap.put(Long.valueOf(category.getId()), labelBOList);
        return labelMap;
    }

}
